// Setup support for prototypal inheritance) 
if (typeof Object.create !== 'function') {
	Object.create = function (o) {
		function F() {}
		F.prototype = o;
		return new F();
	};
}

// closure for namespace safety!
(function($){
	
	var Slide = {
		
		init : function (opts, elem) {

			// overload the passed in options with the default options
			this.options = $.extend({}, this.options, opts);
	
			this.pluginData = {};
			
			// Save the element reference, both as a jQuery reference and a normal reference
			this.elem  = elem;
			this.$elem = $(elem);
			
			this.$displayLengthMinutesSlider = undefined;
			this.$displayLengthSecondsSlider = undefined;
			
			this.order = 0;
		 
			// Build the dom initial structure
			this.buildDom();
			
			// setup the events that pertain to the slide
			this.setupEvents();
		},
		
		options: {
			title: "Untitled",
			slideId : '',
			slideType: '',
			displayLength : 0,
			enabled : 0,
			toggleOpen : 1,
			className : 'thumbnail',
			typeData : {},
			templateOptions : {
        		preserve_template : true
        	}
		},
		
		getPreviewPath : function() {
		    return this.options.previewPath;
		},
		
		setPreviewPath : function(path) {
			this.options.previewPath = path;
		},
		
		getThumbnailPath : function() {
		    return this.options.thumbnailPath;
		},
		
		setThumbnailPath : function(path) {
			this.options.thumbnailPath = path;
			
			if (path !== undefined) {
				this.$elem.find('div.thumbnailPreview').css('background-image', 'url(' + $('#baseUrl').val() + '/' + path + '?t=' + Number(new Date()) + ')');
			}
		},
		
		setPluginData : function(name, data) {
			this.pluginData[name] = data;
		},
		
		getPluginData : function(name) {
			
			if (name === undefined) {
				return this.pluginData;
			}
			
			return this.pluginData[name];
		},
		
		setOrder : function(val) {
			this.order = val;
		},
		
		getOrder : function() {
			return this.order;
		},
		
		setToggleOpen : function(val) {
		    this.options.toggleOpen = val;
		},
		
		getToggleOpen : function() {
		    return this.options.toggleOpen;
		},
		
		setTitle : function(title) {
			this.options.title = title;
			this.$elem.find('.title').text(title);
		},
		
		getTitle : function() {
            return this.options.title;
        },
        
        setDisplayLength : function(val) {
        	
        	this.options.displayLength = val;
        	
        	var minutes = parseInt(parseInt(val, 10) / 60, 10);
	        var seconds = parseInt(val, 10) % 60;
	        
	        this.$elem.find('.expandedDisplayLength').html(UTIL.formatTime(val));
	        this.$elem.find('.headerDisplayLength').html(UTIL.formatTime(val, true));
        },
        
        getDisplayLength : function() {
        	return this.options.displayLength
        },
        
        setEnabled : function(val) {
        	this.options.enabled = val;
        },
        
        getEnabled : function() {
        	return this.options.enabled;
        },
        
        getSlideType : function() {
            return this.options.slideType;
        },
        
        getTypeData : function() {
        	return this.options.typeData;
        },
        
        setTypeData : function(id, value) {
	        this.options.typeData[id] = value;
	    },
        
        getSlideId : function() {
            return this.options.slideId;
        },
        
        setSlideId : function(val) {
        	this.options.slideId = val;
        },
		
		buildDom: function() {
			
        	this.options['checked'] = '';
        	
        	if (this.options['enabled'] == 1) {
        		this.options['checked'] = 'checked="checked"';
        	}
        	
        	//var renderedHtml = $('div.thumbnailTemplate').render(this.options, this.options.templateOptions).html();
        	$.tmpl(this.options.templateName, this.options).appendTo(this.$elem);
        	
        	this.$elem.addClass(this.options.className);
        	
        	this.setThumbnailPath(this.options.thumbnailPath);
	        
	        this.setDisplayLength(this.options.displayLength);
	        
		},
		
		setupEvents: function() {
			
		}
	};
	
	$.fn.extend({
		
        'slide': function(options) {
            return this.each(function() {
            	
                // Create a new slide
                var mySlide = Object.create(Slide);
                
                // Set initialize that slide with the plugin options
                mySlide.init(options, this);
                
                // Save the reference to the slide in the elem's data object
                $(this).data('slide', mySlide);
            });
        }
    });

	var slidestreamId;
	
	var slideList = function() {
	        
	    var config = {};
	    var $addSlideDialog = null;
	    var $totalSlides = null;
	    var $totalRunningTime = null;
	    var $newSlideSelect = null;
	    var $newSlideTypeDescription = null;
	    var $newSlideTypeName = null;
	    var $newSlideTypeTitle = null;
	    var $newSlideTypeIcon = null;
	    var $createSlideButton = null;
	    var $slideTemplate = null;
	    
	    function init(settings) {
	    	
	        config = {
	        		
	            timelineWrapper        : 'div#timeline',
	            $timelineContent       : $('#timelineContent'),
	            $thumbList             : $('#timelineThumbs'),
	            baseUrl                : $('#baseUrl').val(),
	            deleteSelector         : 'input.delete',
	            editSelector           : 'input.edit',
	            toggleExpandedSelector : 'input.toggleExpanded',
	            thumbSelector          : 'div.thumbnail',
	            thumbHandleSelector    : '.handle',
	            templateName		   : 'slideTemplate'
	        };
	        
	        $newSlideSelect          = $('#newSlideSelect');
	        $newSlideTypeDescription = $('#newSlideTypeDescription');
	        $newSlideTypeName        = $('#newSlideTypeName');
	        $newSlideTypeTitle       = $('#newSlideTypeTitle');
	        $newSlideTypeIcon        = $('#newSlideTypeIcon');
	        $createSlideButton       = $('#createSlideButton');
	        
	        $totalSlides             = $('#totalSlides');
	        $totalRunningTime        = $('#totalRunningTime');
	        $addSlideDialog          = $('#addSlideDialog');
	        	    
	        // allow overriding the default config
	        $.extend(config, settings);
	        
	        // create the pre-compiled slide template
	        $('#' + config.templateName).template(config.templateName);
	        
	        initAddSlideDialog();
	        
	        config.$thumbList.sortable({
	            axis: 'y',
	            tolerance: 'pointer',
	            handle: config.thumbHandleSelector,
	            containment: $('#timelineWrapper'),
	            cursor: 'row-resize',
	            scroll: true,
	            stop: function(event, ui) {
	                updateSlideOrder();
	            }
	        });
	        
	        // handle the delete buttons
	        $(config.$thumbList).delegate(config.deleteSelector, 'click', function(e) {
	        	if (confirm('Are you sure you want to delete this slide?')) {
		        	$obj = $(this).closest('div.thumbnail');
		        	$obj.removeData('slide').remove();
		        	updateSlideOrder();
		        	updateTotals();
	        	}
	        	return false;
	        });
	        
	        // handle the toggle expanded buttons
	        $(config.$thumbList).delegate(config.toggleExpandedSelector, 'click', function(e) {
	            
	            var $obj = $(this).parents(config.thumbSelector);
	            var $slide = $obj.data('slide');
	            
	            if ($slide.getToggleOpen() == 1) {
	                $slide.setToggleOpen(0);
	            } else {
	                $slide.setToggleOpen(1);
	            }
	            
	        	$(this).parent().parent().next('div.thumbnailExpandedInfo').slideToggle();
		        $(this).parent().parent().find('.headerDisplayLength').toggle();
	        	return false;
	        });
	        
	        // when a user clicks on an edit button, we'll load all the data
	        // associated with that slide into the correct places    
	        $(config.$thumbList).delegate(config.editSelector, 'click', function(e) {
	        	
	            var $obj = $(this).parents(config.thumbSelector);
	            
	            $(config.thumbSelector).removeClass('selected');
	            $obj.addClass('selected');
	            
	            slideEditor.load($obj);	            
	        });
	    }
	    
	    function loadSlides() {
	        
	        // get all the entities for the timeline
	        $.ajax({
	            url: config.baseUrl + '/slidestream/get-entities?slidestreamId=' + slidestreamId,
	            type: 'GET',
	            dataType: 'json',
	            async: false,
	            success: function(data, textStatus) {
	        	
	                $.each(data.slides, function(index, el) {
	                	
	                	var thumb = $('<div />').slide({
	                        slideId       : el.data.slideId,
	                        slideType     : el.data.slideType,
	                        title         : el.data.title,
	                        displayLength : el.displayLength,
	                        thumbnailPath : el.data.thumbnailPath,
	                        previewPath   : el.data.previewPath,
	                        enabled       : el.enabled,
	                        toggleOpen    : el.toggleOpen,
	                        templateName  : config.templateName,
	                        typeData      : (el.typeData.length == 0) ? {} : el.typeData
	                    });
	                	
	                    // store the data for the plugins into the object
	                    $.each(el.pluginData, function(name, data) {
	                    	thumb.data('slide').setPluginData(name, data);
	                    });
	                    
	                    addSlideToList(thumb);
	                    
	                    initUiElements(thumb);
	                });
	                	                
	                pluginRegistry.setupSlidestreamPlugins(data.slidestreamPlugins);
	                
	            }
	        });
	        
	        updateSlideOrder();
	        updateTotals();
	    }
	    
	    function initUiElements(thumb) {
            
            var checkbox = thumb.find('.toggleEnabled')
            
            checkbox.iphoneStyle();
            
            checkbox.change(function() {
            	
            	var val = 0;
            	
            	if ($(this).is(':checked')) {
            		val = 1;
            	}
            	
            	thumb.data('slide').setEnabled(val);
            	
            	updateTotals();
       		});
            
            var displayLength = thumb.data('slide').getDisplayLength();
            var minutes = parseInt(displayLength / 60, 10);
            var seconds = parseInt(displayLength % 60, 10);
            	                    
            thumb.data('slide').$displayLengthMinutesSlider = thumb.find('.displayLengthMinutesSlider').slider({
	            range: 'min',
	            value: minutes,
	            min: 0,
	            max: 59,
	            slide: function(event, ui) {
	        	
	        		var seconds = parseInt(thumb.data('slide').$displayLengthSecondsSlider.slider('value'), 10);
	        		var minutes = ui.value;
	        		var val = parseInt((minutes * 60) + seconds, 10);
	        		
	        		thumb.data('slide').setDisplayLength(val);
	        		
	        		updateTotals();
	            }
	        });
	        
            thumb.data('slide').$displayLengthSecondsSlider = thumb.find('.displayLengthSecondsSlider').slider({
	            range: 'min',
	            value: seconds,
	            min: 0,
	            max: 59,
	            slide: function(event, ui) {
	        		
	        		var minutes = parseInt(thumb.data('slide').$displayLengthMinutesSlider.slider('value'), 10);
	        		var seconds = parseInt(ui.value, 10);
	        		var val = parseInt((minutes * 60) + seconds, 10);
	        	
	        		thumb.data('slide').setDisplayLength(val);
	        		
	        		updateTotals();
	            }
	        });
            
            if (thumb.data('slide').getToggleOpen() == 0) {
                thumb.find('.thumbnailExpandedInfo').hide();
                thumb.find('.headerDisplayLength').show();
            }
	    }
	    
	    function addNewSlide() {
	    	$addSlideDialog.dialog('open');
	    }
	    
	    function initAddSlideDialog() {
	        
	        $addSlideDialog.dialog({
	            bgiframe: true,
	            height: 500,
	            width: 850,
	            modal: true,
	            autoOpen: false,
	            overlay: { 
	                opacity: 0.5, 
	                background: "black" 
	            }, 
	            buttons: {  
	                "Cancel": function() { 
	                    $(this).dialog("close"); 
	                }
	            },
	            title: 'Add New Slide'
	        });
	        
	        $newSlideSelect.tabs();
	        
	        $addSlideDialog.delegate('a.slideTypeSelector', 'click dblclick', function(e) {
	        	
	            var selectedSlideTypeTitle       = $('.slideTypeTitle', this).text();
	            var selectedSlideTypeDescription = $('.slideTypeDescription', this).text();
	            var selectedSlideTypeName        = $('.slideTypeName', this).text();
	            var selectedSlideTypeIcon        = $(this).parent().css('background-image');
	            	            
	            $newSlideTypeIcon.css('background-image', selectedSlideTypeIcon);
	            $newSlideTypeDescription.html(selectedSlideTypeDescription);
	            $newSlideTypeTitle.html(selectedSlideTypeTitle);
	            $newSlideTypeName.html(selectedSlideTypeName);
	            
	            $createSlideButton.show();
	            
	            if (e.type.toLowerCase() == 'dblclick') {
	            	$createSlideButton.click();
	            }
	            
	            return false;
	        });
	        
	        $('#createSlideButton').click(function(e) {
	            
	        	e.preventDefault();
	            
	            var slideType = $newSlideTypeName.text();

	            var thumb = $('<div />').slide({
                   slideType     : slideType,
                   title         : 'New Slide',
                   displayLength : 5,
                   typeData      : {},
                   templateName  : config.templateName
               });
	           
	           slideList.addSlideToList(thumb);
	           
	           initUiElements(thumb);
	           
	           $addSlideDialog.dialog('close');
	           
	           thumb.find('input.edit').click();
               
               updateTotals();
               slideList.updateSlideOrder();
               
	        });
	        
	    }
	    
	    function addSlideToList(slideObj) {
	        
	    	config.$thumbList.prepend(slideObj);
	    }
	    
	    function updateSlideOrder() {
	        var tmpOrder = 1;
	        $(config.thumbSelector, config.$thumbList).each(function() {
	            $(this).data('slide').setOrder(tmpOrder++);
	        }); 
	    }
	    
	    /**
	     * Saves the slidestream.  It will just return if it's already in progress.  Creates
	     * a JSON string representing the data structure with all it's attributes and any
	     * plugin info associated with it to send to the backend.
	     */
	    function save() {
	        
	        if (infoPane.isSaveDisabled() === true) {
	            return;
	        }
	        
	        infoPane.disableSave();
	        
	        var slideListArray = [];
	
	        var i = 0;
	        $(config.thumbSelector, config.$thumbList).each(function() {
	            
	            var $obj = $(this).data('slide');
	                        
	            slideListArray[i] = {
	                slideId       : $obj.getSlideId(),
	                order         : $obj.getOrder(),
	                displayLength : $obj.getDisplayLength(),
	                enabled       : $obj.getEnabled(),
	                toggleOpen    : $obj.getToggleOpen(),
	            };
	            
	            i++;
	        });
	        
	        var postData = {
	        				 slidestreamInfo: {title : infoPane.getSlidestreamTitle()},
	        				 slides : slideListArray,
	        				 slidestreamPluginData : pluginRegistry.getSlidestreamPluginData()
	        			   };
	        
	        var structureStr = $.toJSON(postData);
	        
	        $.post(
	                config.baseUrl + '/slidestream/save-slidestream',
	                {
	                    slidestreamId: slidestreamId,
	                    data:          structureStr
	                },
	                function(data, textStatus) {
	                    if (data.rc == 1) {
	                        infoPane.showAlert(data.msg);
	                    } else {
	                        alert(data.msg);
	                    }
	                    
	                    infoPane.enableSave();
	                },
	                'json'
	              );
	    }
	    
	    function getTotalRunningTime() {
	    	
	        var totalRunningTimeValue = 0;
	        $(config.thumbSelector, config.$thumbList).each(function() {
	            var $obj = $(this).data('slide');
	            if ($obj.getEnabled() == true) {
	            	totalRunningTimeValue += parseInt($obj.getDisplayLength(), 10);
	            }
	        });
	        
	        return totalRunningTimeValue;
	    }
	   
	    function getSlideCount() {
	        return $(config.thumbSelector, config.$thumbList).length;
	    }
	    
	    function updateTotals() {
	        
	        var totalRunningTimeValue = slideList.getTotalRunningTime();
	        var totalSlidesValue = slideList.getSlideCount();
	            
	        $totalRunningTime.html(UTIL.formatTime(totalRunningTimeValue));
	        $totalSlides.text(totalSlidesValue + " Slide" + ((totalSlidesValue != 1) ? "s" : ""));
	        
	    }
	    
	    return {
	    	init: init,
	    	save: save,
	    	addNewSlide: addNewSlide,
	    	loadSlides: loadSlides,
	    	updateTotals: updateTotals,
	    	getTotalRunningTime: getTotalRunningTime,
	    	getSlideCount: getSlideCount,
	    	addSlideToList: addSlideToList,
	    	updateSlideOrder: updateSlideOrder
	    };
	}();
	
	var infoPane = function() {
	        
		var config = {};
	    var $saveSlidestreamButton = null;
	    var $addSlideButton = null;
	    var $slidestreamTitle = null;
	    var $statusAlert = null;
	        
	    function init(settings) {
	        
	    	config = { 
	            baseUrl : $('#baseUrl').val()
	        };
	    	
	    	$.extend(config, settings);
	        
	        $saveSlidestreamButton   = $('#saveSlidestreamButton');
	        $addSlideButton          = $('#addSlideButton');
	        $slidestreamTitle        = $('input#slidestreamTitle');
	        $statusAlert             = $('#statusAlert');
	        
	        $statusAlert.hide();
	        
	        $saveSlidestreamButton.click(function(e) {
	        	e.preventDefault();
	            slideList.save();
	        });
	        
	        $addSlideButton.click(function() {
	            slideList.addNewSlide();
	        });
	    }
	    
	    function showAlert(msg) {
	    	
	    	$statusAlert.text(msg)
	    		        .fadeIn()
	    		        .delay(1000)
	    		        .fadeOut();
	    }
	    
	    function getSlidestreamTitle() {
	    	return $slidestreamTitle.val()
	    }
	    
	    function isSaveDisabled() {
	        return $saveSlidestreamButton.attr('disabled');
	    }
	    
	    function disableSave() {
	        $saveSlidestreamButton.attr('disabled', true)
	                              .addClass('ui-state-disabled')
	                              .val('Saving...');
	    }
	    
	    function enableSave() {
	        $saveSlidestreamButton.attr('disabled', false)
	                              .removeClass('ui-state-disabled')
	                              .val('Save Slide Stream');
	    }
	    
	    return {
	    	init: init,
	    	isSaveDisabled: isSaveDisabled,
	    	disableSave: disableSave,
	    	enableSave: enableSave,
	    	getSlidestreamTitle: getSlidestreamTitle,
	    	showAlert: showAlert
	    };
	}();

	var pluginRegistry = function() {
	    
		var config = {};
		var slidePlugins = {};
	    var slidestreamPlugins = {};
	        
	    function init(settings) {
	    
	        config = {
	            baseUrl              : $('#baseUrl').val(),
	            $slidestreamSettings : $('#slidestreamSettings')
	        };
	        
	        $.extend(config, settings);
	        config.$slidestreamSettings.tabs({});
	    }
	    
	    /**
	     * Slidestream plugins store their own data since it's just for the 
	     * slidestream itself.
	     * 
	     * @param pluginData An object literal keyed on the plugin name containing
	     *                   an object literal with the values for the plugin
	     */
	    function setupSlidestreamPlugins(pluginData) {
	    	
	    	// this stuff applies only to slidestream plugins 
	    	// have each slidestream plugin set it's own data
	    	$.each(pluginData, function(name, data) {
	        	var m = getSlidestreamPlugin(name);
	        	m.setData(data);
	        });
	    }
	       
	    function getSlidestreamPluginData(pluginName) {
	    	
	    	if (pluginName != undefined) {
	    		
	    		return slidestreamPlugin.getData();
	    		
	    	} else {
	    		
	    		var data = {};
	    		
	    		$.each(slidestreamPlugins, function(pluginName, plugin) {
	    			data[pluginName] = plugin.getData();
	    		});
	    		return data;
	    	}
	    }
	   
	    function getSlidestreamPlugin(pluginName) {
	    	return slidestreamPlugins[pluginName];
	    }
	    
	    function getSlidestreamPlugins() {
	    	return slidestreamPlugins;
	    }
	    
	    function getSlidePlugins() {
	    	return slidePlugins;
	    }
	    
	    function registerSlidePlugin(pluginName, plugin) {
	        slidePlugins[pluginName] = plugin;
	    }
	    
	    function registerSlidestreamPlugin(pluginName, plugin) {
	        slidestreamPlugins[pluginName] = plugin;
	    }
	    
	    function getSlidePlugin(pluginName) {
	    	return slidePlugins[pluginName];
	    }
	    
	    function isSlidePluginRegistered(name) {
	    	if (slidePlugins[name] != undefined) {
	    		return true;
	    	}
	    	
	    	return false;
	    }
	    
	    function isSlidestreamPluginRegistered(name) {
	    	if (slidestreamPlugins[name] != undefined) {
	    		return true;
	    	}
	    	
	    	return false;
	    }
	    
	    return {
	    	init: init,
	    	getSlidestreamPlugins: getSlidestreamPlugins,
	    	getSlidePlugins: getSlidePlugins,
	    	getSlidestreamPlugin: getSlidestreamPlugin,
	    	getSlidestreamPluginData: getSlidestreamPluginData,
	    	setupSlidestreamPlugins: setupSlidestreamPlugins,
	    	registerSlidestreamPlugin: registerSlidestreamPlugin,
	    	registerSlidePlugin: registerSlidePlugin,
	    	getSlidePlugin: getSlidePlugin,
	    	getSlidestreamPlugin: getSlidestreamPlugin,
	    	isSlidePluginRegistered: isSlidePluginRegistered,
	    	isSlidestreamPluginRegistered: isSlidestreamPluginRegistered
	    };
	
	}();
	
	var slideEditor = function() {
	    
	    var $image = null;
	    var $content = null;
	    var $title = null;
	    var $previewLink = null;
	    var $dialog = null;
	    var config = {};
	        
	    function init(settings) {
	    
	        config = {
	            baseUrl : $('#baseUrl').val(),
	            slideTypeSettingsUrl : '/slidestream/get-slide-settings-form'
	        };
	        
	        imageSelector          = '#previewImage';
	        $content               = $('#previewPaneContent');
	        $title                 = $('#previewInfoTitle');
	        $dialog                = $('#editSlideDialog');
	        $slidePluginsContainer = $('#slidePlugins');
            $typeSettings          = $('#typeSettingsFormContainer');
            typeSettingsSelector   = '#typeSettingsFormContainer';
	
	        // allow overriding the default config
	        $.extend(config, settings);
	        
	        initEditDialog();
	        $slidePluginsContainer.tabs({});
	    }
	    
	    function initEditDialog() {
	        
	        $dialog.dialog({
	            bgiframe: true,
	            height: 500,
	            width: 900,
	            modal: true,
	            autoOpen: false,
	            open: function() {
	        	},
	            overlay: { 
	                opacity: 0.6, 
	                background: "black" 
	            }, 
	            buttons: {
	                "Cancel": function() { 
	            	    $(this).find('input[type=text], textarea, input[type=radio], select').val('');
	            	    $dialog.find('.wysiwyg').remove();
	                    $(this).dialog("close");
	                    
	                    $slideDom = $dialog.data('slideDom');
	                    $slide = $dialog.data('slide');
	                    
	                    if ($slide.getSlideId() == '') {
	                    	// remove slide
	                    	$slideDom.removeData('slide').remove();
	    		        	slideList.updateSlideOrder();
	    		        	slideList.updateTotals();
	                    }
	                },
	                "Save" : function() {
	                	save(); 
	            	}
	            },
	            title: 'Edit Slide'
	        });
	    }
	    
	    function load($obj) {
	    	
	    	// temporarily keep the object in the dialog's data so we can get access to it on save
	    	$slide = $obj.data('slide');
	    	
	    	$dialog.data('slide', $slide);
	    	$dialog.data('slideDom', $obj);
	    	
	    	var previewPath = $slide.getPreviewPath();
	    	
	    	if (previewPath !== undefined) {
	    		$(imageSelector).css('background-image', 'url(' + config.baseUrl + '/' + previewPath + '?t=' + Number(new Date()) + ')');
	    	}
	        
	    	$title.val($slide.getTitle());
	        
	        // load the type settings for for this type of slide
            loadTypeSettingsForm($slide.getSlideType(), $obj);
            
            // load plugin data for the slide if it exists
            $.each(pluginRegistry.getSlidePlugins(), function(pluginName, plugin) {
                
                var pluginData = $slide.getPluginData(pluginName);
                
                // empty the input fields for the plugin so we can make sure we populate them
                // all with the correct plugin data
            	$(this).find('input[type=text], textarea, input[type=radio], select').val('');
                
            	// load the data into the plugin
               	pluginRegistry.getSlidePlugin(pluginName).loadData(pluginData);
            });
	    	
	    	$dialog.dialog('open');
	    }
	    
	    function save() {
	    	
	    	$slide = $dialog.data('slide');
	    	
	    	$slide.setTitle($title.val());
	    	slideList.updateTotals();
	    	
	    	$('input, select, textarea', $(typeSettingsSelector)).each(function() {
	    		$slide.setTypeData($(this).attr('id'), $(this).val());
	    	});
	    	
	    	// save the plugin data for the slide if the plugin's update method exists
	        $.each(pluginRegistry.getSlidePlugins(), function(pluginName, plugin) {
	            
	            if ($.isFunction(plugin.update)) {
	            	plugin.update($slide);
	            }
	        });
	        
	        var slideData = $.toJSON({
	        	
             	slidestreamId : slidestreamId,
             	slideId       : $slide.getSlideId(),
                slideType     : $slide.getSlideType(),
                title         : $slide.getTitle(),
                pluginData    : $slide.getPluginData(),
                typeData      : $slide.getTypeData()
                
            });
	        
	        $.post(config.baseUrl + '/slide/save',
					 {
	        			data: slideData
					 },
	                 function(data, textStatus) {
	                       
	                	 if (data.rc === 0) {
	                		 alert(data.msg);
	                         return;
	                     } else {
	                    	 // we need to assign it the slide ID
	             	    	 if ($slide.getSlideId() == '') {
	             	    		 $slide.setSlideId(data.slideId);
	             	    	 }
	             	    	 
	             	    	 if (data.updateImages == true) {
	             	    		$slide.setThumbnailPath(data.thumbnailPath);
	             	    		$slide.setPreviewPath(data.previewPath);
	             	    	 }
	             	    	 
	             	    	 $dialog.removeData('slide');
	             	    	 $dialog.find('.wysiwyg').remove();
	             	    	 $dialog.find('input[type=text], textarea, input[type=radio], select', $dialog).val('');
			            	 $dialog.dialog("close");
	                     }
	                 },
	                 'json'
	        );
	    }
	    
	    function getTypeSettingsObj() {
	    	return $typeSettings;
	    }
	    
	    function loadTypeSettingsForm(type, $obj) {
	    	
	        $typeSettings.load(
                            config.baseUrl + config.slideTypeSettingsUrl + '?type=' + type,
                            function(data) {
                            	loadTypeSettingsDataCb(data, $obj);
                            }
	        );
	    }
	    
	    function loadTypeSettingsDataCb(data, $obj) {
	    	
	    	$slide = $obj.data('slide');
	    	
	    	$.each($slide.getTypeData(), function(index, val) {
	        	$('#' + index, getTypeSettingsObj()).val(val);
	        });
	    	
	    	jscolor.init();
	    	
	    	$('textarea.richtext').wysiwyg({
	    		
	    		controls: {
	    	      strikeThrough : { visible : true },
	    	      underline     : { visible : true },
	    	      
	    	      separator00   : { visible : true },
	    	      
	    	      justifyLeft   : { visible : true },
	    	      justifyCenter : { visible : true },
	    	      justifyRight  : { visible : true },
	    	      justifyFull   : { visible : true },
	    	      
	    	      separator01   : { visible : true },
	    	      
	    	      indent        : { visible : true },
	    	      outdent       : { visible : true },
	    	      
	    	      separator02  : { visible : true },
	    	      
	    	      subscript    : { visible : true },
	    	      superscript  : { visible : true },
	    	      
	    	      separator03  : { visible : true },
	    	      
	    	      undo         : { visible : true },
	    	      redo         : { visible : true },
	    	      
	    	      separator04  : { visible : true },
	    	      
	    	      insertOrderedList    : { visible : true },
	    	      insertUnorderedList  : { visible : true },
	    	      insertHorizontalRule : { visible : true },

	    	      separator07  : { visible : true },
	    	      
	    	      cut          : { visible : true },
	    	      copy         : { visible : true },
	    	      paste        : { visible : true },
	    	      html         : { visible : true }
	    	    }
	    	});
	        
	        $('form').submit(function(e) {
	    		e.preventDefault();
	    	});
	    }
	    
	    return {
	    	init: init,
	    	load: load,
	    	loadTypeSettingsForm: loadTypeSettingsForm,
	    	getTypeSettingsObj: getTypeSettingsObj
	    };
	}();
	
	var devices = function() {
		
		var config = {};
	    var $addDeviceDialog = null;
	    var $deviceSelect = null;
	    var $assignDeviceButton = null;
	    var $addDeviceButton = null;
	    var $toggleDeviceListButton = null;
	    
	    var $deviceDescription = null;
	    var $deviceName = null;
	    var $deviceIp = null;
	    var $deviceIcon = null;
	    var $deviceLat = null;
	    var $deviceLng = null;
	    var $deviceId = null;
	    	    
	    var $deviceCount = null;
		
		var $map;
		var $list;
		var inListView = false;
		
		var infowindow = null;
		var devices = [];
		
		var initialLocation = null;
		
		var numDevices = 0;

		function init() {
			
			var baseUrl = $('#baseUrl').val();
			
			var mapOptions = {
			    zoom: 12,
			    mapTypeControl: false,
			    navigationControl: true,
			    navigationControlOptions: {
			        style: google.maps.NavigationControlStyle.SMALL
			    },
			    streetViewControl: false,
			    mapTypeId: google.maps.MapTypeId.ROADMAP
			};
			
			initialLocation = new google.maps.LatLng(40.69847032728747, -73.9514422416687);
			
			$deviceSelect        = $('#deviceSelect');
	        $assignDeviceButton  = $('#assignDeviceButton');
	        $addDeviceDialog     = $('#addDeviceDialog');
	        $addDeviceButton     = $('#addDeviceButton');
	        
	        $toggleDeviceListButton = $('#showDeviceListButton');
	        
	        $deviceDescription = $('#deviceDescription');
	        $deviceName = $('#deviceName');
	        $deviceIp = $('#deviceIp');
	        $deviceIcon = $('#deviceIcon');
	        $deviceLat = $('#deviceLat');
	        $deviceLng = $('#deviceLng');
	        $deviceId = $('#deviceId');
	        $deviceSearch = $('#deviceSearch');

	        $deviceMap = $('#deviceMap');
	        $deviceList = $('#deviceList');
	        $deviceListWrapper = $('#deviceListWrapper');
			
			$deviceCount = $('#deviceCount');
			
			initAddDeviceDialog();
			
			$addDeviceButton.click(function() {
	            addDevice();
	        });
			
			$('input.unassignDevice').live('click', function(e) {
            	e.preventDefault();
            	var deviceId = $(this).attr('id').split('_');
            	deviceId = deviceId[1];
            	unassignDevice(deviceId);
            });
			
			$deviceSearch.keyup(function (e) {
			    var filter = $(this).val();
			    $('.deviceListDevice', $deviceList).each(function () {
			    	var deviceId = $(this).attr('id').replace('deviceListDevice_', '');
			    	var $thisDevice = devices[deviceId];
			        if ($thisDevice.searchString.search(new RegExp(filter, 'i')) < 0) {
			            $(this).hide();
			        } else {
			            $(this).show();
			        }
			    });
			});
			
			$toggleDeviceListButton.click(function(e) {
				
				if ($deviceMap.is(':visible')) {
					$(this).html('Map View<span class="ui-icon ui-icon-pin-s"></span>');
					$deviceMap.hide();
					$deviceListWrapper.show();
					inListView = true;
				} else {
					$(this).html('List View<span class="ui-icon ui-icon-document"></span>');
					$deviceMap.show();
					$deviceListWrapper.hide();
					inListView = false;
				}
			});
			
			numDevices = 0;
			
			$map = new google.maps.Map(document.getElementById("deviceMap"), mapOptions);
			infoWindow = new google.maps.InfoWindow();
			
			load();
		}
		
		// load all the signs that have this slidestream assigned to them
		function load() {
			
	        $.ajax({
	            url: baseUrl + '/slidestream/get-devices?slidestreamId=' + slidestreamId,
	            type: 'GET',
	            dataType: 'json',
	            sync: false,
	            success: function(data, textStatus) {
	        	
	        		if (data.length == 1) {
	        			var str = data.length + ' Digital Sign Assigned';        		
	        		} else {
	        			var str = data.length + ' Digital Signs Assigned';
	        		}
	        		
	        		numDevices = data.length;
	        		
	        		setDeviceCountString(numDevices);
	        	
	        		if (numDevices > 0) {
	        			initialLocation = new google.maps.LatLng(data[0].lat, data[0].lng);
	        		}
	        		
	                $.each(data, function(index, el) {
	                	addMarker(el.lat, el.lng, el.name, el.ip, el.deviceId);
	                });
	                
	                $map.setCenter(initialLocation);
	            }
	        });
	        
		}
		
		function addListItem(device) {
			
			var content = '<div class="deviceListDevice" id="deviceListDevice_' + device.data.deviceId + '">' 
						+ device.data.name + ' - ' + device.data.ip + ' '  
            			+ '<input type="button" class="unassignDevice" id="unassign_' + device.data.deviceId + '" value="Unassign Device" />'
            			+ '</div>';
			
            $deviceList.append(content);

            stripeDeviceListRows();
		}
		
		
		function stripeDeviceListRows() {
			$deviceList.find('.deviceListDevice').removeClass('row1 row2');
			$('.deviceListDevice:odd', $deviceList).addClass('row1');
			$('.deviceListDevice:even', $deviceList).addClass('row2');
		}
		
		function addMarker(latitude, longitude, name, ip, deviceId, panToMarker) {
			
			if (panToMarker == undefined) {
				panToMarker = false;
			}
			
			var thisLatLng = new google.maps.LatLng(latitude, longitude);
			
			devices[deviceId] = {
				data : {
					name: name,
					ip: ip,
					deviceId: deviceId,
					latitude: latitude,
					longitude: longitude
				},
				searchString : name + ' ' + ip,
				marker: new google.maps.Marker({
			        position: thisLatLng, 
			        map: $map,
			        title: name
			    })
			};
			
			google.maps.event.addListener(devices[deviceId].marker, 'click', function() {
				var content = name + ' - ' + ip + '<br />'
				            + '<input type="button" class="unassignDevice" id="unassign_' + deviceId + '" value="Unassign Device" />';
				infoWindow.setContent(content);
				infoWindow.open($map, devices[deviceId].marker);
			});
			
			if (panToMarker !== false) {
				$map.panTo(thisLatLng);
			}
			
			addListItem(devices[deviceId]);
		}
		
		// if a device id is passed, it'll be selected
		function addDevice(deviceId) {
			$.get($('#baseUrl').val() + '/slidestream/get-unassigned-devices',
				  function(data){
					$('#add_my_device').html(data);
					$addDeviceDialog.dialog('open');
					if (deviceId !== undefined) {
						$('#deviceWrapper_' + deviceId).find('a.deviceSelector').click();
					}
				  },
				  'html'
			);	    	
	    }
	    
	    function initAddDeviceDialog() {
	        
	        $addDeviceDialog.dialog({
	            bgiframe: true,
	            height: 500,
	            width: 850,
	            modal: true,
	            autoOpen: false,
	            overlay: { 
	                opacity: 0.5, 
	                background: "black"
	            }, 
	            buttons: {  
	                "Cancel": function() { 
	                    $(this).dialog("close"); 
	                }
	            },
	            title: 'Assign a New Device'
	        });
	        
	        $deviceSelect.tabs();
	        
	        $addDeviceDialog.delegate('a.deviceSelector', 'click dblclick', function(e) {
	        	
	            var selectedDeviceIp          = $('.deviceIp', this).text();
	            var selectedDeviceDescription = $('.deviceDescription', this).text();
	            var selectedDeviceName        = $('.deviceName', this).text();
	            var selectedDeviceLng         = $('.deviceLng', this).val();
	            var selectedDeviceLat         = $('.deviceLat', this).val();
	            var selectedDeviceId          = parseInt($('.deviceId', this).val(), 10);
	            var selectedDeviceIcon        = $(this).parent().css('background-image');
	            	            
	            $deviceIcon.css('background-image', selectedDeviceIcon);
	            $deviceDescription.html(selectedDeviceDescription);
	            $deviceIp.html(selectedDeviceIp);
	            $deviceName.html(selectedDeviceName);
	            $deviceLng.val(selectedDeviceLng);
	            $deviceLat.val(selectedDeviceLat);
	            $deviceId.val(selectedDeviceId);
	            
	            if (selectedDeviceId == 0) {
	            	$assignDeviceButton.val('Create New Device');
	            } else {
	            	$assignDeviceButton.val('Assign Device');
	            }
	        	
	            $assignDeviceButton.show();
	            
	            if (e.type.toLowerCase() == 'dblclick') {
	            	$assignDeviceButton.click();
	            }
	        });
	        
	        $('#assignDeviceButton').click(function(e) {
	            
	        	e.preventDefault();
	            
	            var name = $deviceName.text();
	            var ip = $deviceIp.text();
	            var lat = $deviceLat.val();
	            var lng = $deviceLng.val();
	            var deviceId = $deviceId.val();
	            
	            // we're adding a new device instead of adding an existing one
	            if (deviceId == 0) {
	            	
	            	if (confirm("You will be redirected to add a new device, and you will automatically return here when you're done.\n\nYou will lose all unsaved changes!\n\nAre you sure you want to continue?")) {
		            	window.location.href = $('#baseUrl').val() + '/devices/add/redirect/' + slidestreamId;	           	
	            	}
	            	
	            	return;
	            }

	            addMarker(lat, lng, name, ip, deviceId, true);
	            
	            $.post(
	            	$('#baseUrl').val() + '/slidestream/assign-device',
	            	{
	            		slidestreamId: slidestreamId,
	            		deviceId: deviceId
	            	}, function(data, textStatus, XMLHttpRequest) {
	            		
	            		if (parseInt(data.rc, 10) == 1) {
	            		
	            			numDevices++;
	            		
	            			setDeviceCountString(numDevices);
	            			
	            		} else {
	            			alert(data.msg);
	            		}
	            		
	            		$deviceIcon.css('background-image', '');
	    	            $deviceDescription.html('');
	    	            $deviceIp.html('');
	    	            $deviceName.html('');
	    	            $deviceLng.val('');
	    	            $deviceLat.val('');
	    	            $deviceId.val('');
	    	            
	    	            $assignDeviceButton.hide();
	            	},
	            	'json'
	            );
	            
	            $addDeviceDialog.dialog('close');
	            
	        });
	    }
	    
	    function unassignDevice(deviceId) {
	    	
	    	$('.unassignDevice').attr('disabled', true);
	    	
	    	$.post(
	            	$('#baseUrl').val() + '/slidestream/unassign-device',
	            	{
	            		slidestreamId: slidestreamId,
	            		deviceId: deviceId
	            	}, function(data, textStatus, XMLHttpRequest) {
	            		
	            		if (parseInt(data.rc, 10) == 1) {
	            		
	            			numDevices--;
	            		
	            			devices[deviceId].marker.setMap(null);
	            			$('#deviceListDevice_' + deviceId).remove();
	            			stripeDeviceListRows();
	            			infoWindow.close();
	            			delete devices[deviceId];
	            			
	            			setDeviceCountString(numDevices);
	            			
	            		} else {
	            			alert(data.msg);
	            		}
	            		
	            		$('.unassignDevice').attr('disabled', false);
	            	},
	            	'json'
	            );
	    }
	    
	    function setDeviceCountString(count) {
	    	
	    	if (count == 1) {
    			var str = count + ' Digital Sign Assigned';        		
    		} else {
    			var str = count + ' Digital Signs Assigned';
    		}
	    	
	    	$deviceCount.text(str);
	    }
		
		return {
			init: init,
			add: addDevice,
			load: load
		}
		
	}();
	
	
	$(document).ready(function() {
	
	    slidestreamId = $('#slidestreamId').val();
	    
	    slideList.init();
	    slideEditor.init();
	    pluginRegistry.init();
	    devices.init();
	    infoPane.init();
	    
	    /**
	     * Initialize the plugins we want to use
	     */
	    schedulePlugin.init();
	    transitionPlugin.init();
	    marqueePlugin.init();
	    
	    slideList.loadSlides(); // load the slides after the interface has been setup
	    
	    // if it was a redirect from adding a device, let's load up the assign device dialog
	    if (parseInt($('#deviceRedirect').val(), 10) != 0) {
	    	devices.add(parseInt($('#deviceRedirect').val(), 10));
	    }
	});
	
	
	/**
	 * Various utilities that are used by multiple objects
	 */
	var UTIL = {
	        
	        /**
	         * Adds the hover classes and round corners to newly created buttons
	         */
	        themeButtons: function(scope) {
	
	            scope = $(scope);
	            $('input[type=submit], input[type=button], input[type=reset], button', scope).addClass('ui-state-default ui-corner-all');
	            $('a.ui-state-default, input.ui-state-default, button.ui-state-default', scope).hover(
	                function(){ $(this).addClass('ui-state-hover'); }, 
	                function(){ $(this).removeClass('ui-state-hover'); }
	            );
	        },
	
	        /**
	         * Returns a string like "1 minute 40 seconds" given a number of seconds, or
	         * if the short param is set to true it will return a shortened version like
	         * "1m40s"
	         * 
	         * @param int|string seconds The number of seconds to format
	         * @param bool If true returns format like 1m2s
	         */
	        formatTime: function(seconds, short) {
	            
	            short = short || false;
	            
	            seconds = parseInt(seconds, 10);
	            
	            var mins = parseInt(seconds / 60, 10);
	            var secs = parseInt(seconds % 60, 10);
	            
	            var minsUnit = ' mins ';
	            var secsUnit = ' secs';
	            
	            if (mins == 1) {
	                minsUnit = ' min ';
	            }
	            
	            if (secs == 1) {
	                secsUnit = ' sec';
	            }
	            
	            if (short === true) {
	                minsUnit = 'm ';
	                secsUnit = 's';
	            }
	            
	            return mins + '<span class="unitMin">' + minsUnit + '</span>' + secs + '<span class="unitSec">' + secsUnit + '</span>';
	        } 
	};
	
	/**
	 * Sets up the all the interaction for the marquee slidestream plugin
	 * 
	 * All interaction with the plugin will operate on the data for the slidestream
	 */
	var marqueePlugin = {
		
		config : {},
		name : 'Marquee',
		$context : null,
		
		init : function (settings) {
	
	        this.config = {
	            baseUrl              : $('#baseUrl').val(),
	            enabledSelector      : 'select#enabledMarquee',
	            typeSelector         : 'select#typeMarquee',
	            urlSelector          : 'input#urlMarquee',
	            rssModeSelector      : 'select#rssModeMarquee',
	            textSelector         : 'textarea#textMarquee',
	            positionSelector     : 'select#positionMarquee',
	            textColorSelector    : 'input#textColorMarquee',
	            fontFamilySelector   : 'select#fontFamilyMarquee',
	            fontSizeSelector     : 'select#fontSizeMarquee',
	            bgColorSelector      : 'input#bgColorMarquee',
	            opacitySelector      : 'select#opacityMarquee',
	            effectSelector       : 'select#effectMarquee',
	            bgColorPickerClass   : 'bgColorPickerMarquee',
	            textColorPickerClass : 'textColorPickerMarquee'
	        };
	        
	        this.$context = $('#' + this.name);
	        
	        $.extend(this.config, settings);
	        
	        pluginRegistry.registerSlidestreamPlugin(this.name, this);
	        
	        var config = this.config;
	        $(this.config.typeSelector).change(function(e) {

	        	if ($(this).val() == 'rss') {
	        		$('#fieldset-textDisplayGroupMarquee', this.$context).hide();
	        		$('#fieldset-urlDisplayGroupMarquee', this.$context).show();
	        	} else if ($(this).val() == 'text') {
	        		$('#fieldset-textDisplayGroupMarquee', this.$context).show();
	        		$('#fieldset-urlDisplayGroupMarquee', this.$context).hide();
	        	}
	        });
	    },
	    
	    getName : function() {
	    	return this.name;
	    },
	    
	    setData : function(data) {
	    	
	    	if (!$.isEmptyObject(data)) {
	    	
		    	$(this.config.enabledSelector, this.$context).val(data['enabled']);
		    	$(this.config.typeSelector, this.$context).val(data['type']);
		    	$(this.config.urlSelector, this.$context).val(data['url']);
		    	$(this.config.rssModeSelector, this.$context).val(data['rssMode']);
		    	$(this.config.textSelector, this.$context).val(data['text']);
		    	$(this.config.positionSelector, this.$context).val(data['position']);
		    	$(this.config.textColorSelector, this.$context).val(data['textColor']);
		    	$(this.config.fontFamilySelector, this.$context).val(data['fontFamily']);
		    	$(this.config.fontSizeSelector, this.$context).val(data['fontSize']);
		    	$(this.config.bgColorSelector, this.$context).val(data['bgColor']);
		    	$(this.config.opacitySelector, this.$context).val(data['opacity']);
		    	$(this.config.effectSelector, this.$context).val(data['effect']);
		    	
		    	$(this.config.typeSelector, this.$context).change();
	    	}
	    },
	    
	    getData : function() {
	    	
	        var data = {
	        	enabled    : $(this.config.enabledSelector, this.$context).val(),
	            type       : $(this.config.typeSelector, this.$context).val(),
	            url        : $(this.config.urlSelector, this.$context).val(),
	            rssMode    : $(this.config.rssModeSelector, this.$context).val(),
	            text       : $(this.config.textSelector, this.$context).val(),
	            position   : $(this.config.positionSelector, this.$context).val(),
	            textColor  : $(this.config.textColorSelector, this.$context).val(),
	            fontFamily : $(this.config.fontFamilySelector, this.$context).val(),
	            fontSize   : $(this.config.fontSizeSelector, this.$context).val(),
	            bgColor    : $(this.config.bgColorSelector, this.$context).val(),
	            opacity    : $(this.config.opacitySelector, this.$context).val(),
	            effect     : $(this.config.effectSelector, this.$context).val()
	        };
	        
	        return data;
	    }
	};
	
	/**
	 * Sets up the all the interaction for the schedule plugin
	 * 
	 * All interaction with the plugin will operate on the data that is passed to it
	 */
	var schedulePlugin = {
	
		name : 'Schedule',
	    config : {},
		
	    init : function(settings) {
	    
	        this.config = {
	            baseUrl      : $('#baseUrl').val(),
	            fromDate     : 'input#fromDate',
	            toDate       : 'input#toDate',
	            fromHour     : 'select#fromHour',
	            fromMinute   : 'select#fromMinute',
	            fromMeridian : 'select#fromMeridian',
	            toHour       : 'select#toHour',
	            toMinute     : 'select#toMinute',
	            toMeridian   : 'select#toMeridian',
	            noToDate     : 'input[name="noToDate"]',
	            noFromDate   : 'input[name="noFromDate"]'
	        };
	        
	        $.extend(this.config, settings);
	        
	        $(this.config.fromDate + ', ' + this.config.toDate).css('width', '100px').datepicker({
	        	defaultDate: null
	        });
	        
	        var thisConfig = this.config;
	        
	        $(this.config.noFromDate).bind('setupCheckedStatus', function() {
	        	if ($(this).is(':checked')) {
	        		$(thisConfig.fromHour + ', ' + thisConfig.fromMinute + ', ' + thisConfig.fromMeridian).val('').attr('disabled', true);
	        		$(thisConfig.fromDate).val('').datepicker('disable');
	        	} else {
	        		$(thisConfig.fromHour + ', ' + thisConfig.fromMinute + ', ' + thisConfig.fromMeridian).attr('disabled', false);
	        		$(thisConfig.fromDate).datepicker('enable');
	        	}
	        }).click(function() {
	        	$(this).trigger('setupCheckedStatus');
	        });
	        
	        $(this.config.noToDate).bind('setupCheckedStatus', function() {
	        	if ($(this).is(':checked')) {
	        		$(thisConfig.toHour + ', ' + thisConfig.toMinute + ', ' + thisConfig.toMeridian).val('').attr('disabled', true);
	        		$(thisConfig.toDate).val('').datepicker('disable');
	        	} else {
	        		$(thisConfig.toHour + ', ' + thisConfig.toMinute + ', ' + thisConfig.toMeridian).attr('disabled', false);
	        		$(thisConfig.toDate).datepicker('enable');
	        	}
	        }).click(function() {
	        	$(this).trigger('setupCheckedStatus');
	        });
	        
	        $.extend(this.config, settings);
	        
	        pluginRegistry.registerSlidePlugin(this.name, this);
	    },
	    
	    getName : function() {
	    	return this.name;
	    },
	    
	    /**
	     * Updates the values for the plugin with reference to the passed slide
	     * object
	     * 
	     * @param $slide Reference to the slide to act upon
	     * @return
	     */
	    update : function($slide) {
	       	    	
            var noFromDate = $(this.config.noFromDate + ':checked').length;
            var noToDate   = $(this.config.noToDate + ':checked').length;
	    	
	    	var fromTs = 0;
	    	var toTs = 0;
	    	
	    	if ($(this.config.fromDate).val() != '' && noFromDate == 0) {
	    	
		    	// build timestamp from the individual time fields
		    	var fromDt = new Date($(this.config.fromDate).val());
		    	
		    	var hour = parseInt($(this.config.fromHour).val(), 10);
		    	var minute = parseInt($(this.config.fromMinute).val(), 10);
		    	var meridian = $(this.config.fromMeridian).val();
		    	if (meridian == 'PM') {
		    		hour += 12;
		    	}
		    	
		    	if (hour == 12 && meridian == 'AM') {
		    		hour = 0;
		    	}
		    	
		    	if (hour == 24 && meridian == 'PM') {
		    		hour = 12;
		    	}
		    	
		    	fromDt.setHours(hour);
		    	fromDt.setMinutes(minute);
		    	
		    	fromTs = parseInt(fromDt.getTime() / 1000, 10);
	    	}
	    	
	    	if ($(this.config.toDate).val() != '' && noToDate == 0) {
	    		
		    	var toDt = new Date($(this.config.toDate).val());
		    	
		    	var hour = parseInt($(this.config.toHour).val(), 10);
		    	var minute = parseInt($(this.config.toMinute).val(), 10);
		    	var meridian = $(this.config.toMeridian).val();
		    	if (meridian == 'PM') {
		    		hour += 12;
		    	}
		    	
		    	if (hour == 12 && meridian == 'AM') {
		    		hour = 0;
		    	}
		    	
		    	if (hour == 24 && meridian == 'PM') {
		    		hour = 12;
		    	}
		    	
		    	toDt.setHours(hour);
		    	toDt.setMinutes(minute);
		    	
		    	toTs = parseInt(toDt.getTime() / 1000, 10);
	    	}
	    	
	    	// we want to store seconds, not milliseconds so we divide by 1000
	    	var pluginData = {
	    		fromDt: fromTs,
	    		toDt: toTs
	    	};

	        $slide.setPluginData(this.name, pluginData);
	    },
	    
	    loadData : function(pluginData) {
	    	
	        var fromDtTs = 0;
	        var toDtTs = 0;
	        
	    	if (pluginData !== undefined && pluginData.fromDt !== undefined) {
	    		fromDtTs = parseInt(pluginData.fromDt, 10);
	    	}
	    	
	    	if (pluginData !== undefined && pluginData.toDt !== undefined) {
	    		toDtTs = parseInt(pluginData.toDt, 10);
	    	}
	    		    	
	    	if (fromDtTs === 0) {
    			$(this.config.noFromDate).attr('checked', true);
    			
    		} else {
    			
    			$(this.config.noFromDate).attr('checked', false);
    			
    			var fromDt = new Date(fromDtTs * 1000); // we need milliseconds
    			
    			$(this.config.fromDate).val($.datepicker.formatDate('mm/dd/yy', fromDt));
    			
    			var hour = fromDt.getHours();
    			var meridian = 'AM';
    			
    			if (hour > 12) {
    				hour -= 12;
    				meridian = 'PM';
    			}
    			
    			if (hour == 12) {
    				meridian = 'PM';
    			}
    			
    			if (hour == 0) {
    				hour = 12;
    				meridian = 'AM';
    			}
    			
    			var minute = fromDt.getMinutes();
    			
    			$(this.config.fromHour).val(hour);
    			$(this.config.fromMinute).val(minute);
    			$(this.config.fromMeridian).val(meridian);
            }
	    	
	    	if (toDtTs === 0) {
    			$(this.config.noToDate).attr('checked', true);
    			
    		} else {
    			
    			$(this.config.noToDate).attr('checked', false);
    			
    			var toDt = new Date(toDtTs * 1000); // we need milliseconds
    			
    			$(this.config.toDate).val($.datepicker.formatDate('mm/dd/yy', toDt));
    			
    			var hour = toDt.getHours();
    			var meridian = 'AM';
    			
    			if (hour > 12) {
    				hour -= 12;
    				meridian = 'PM';
    			}
    			
    			if (hour == 12) {
    				meridian = 'PM';
    			}
    			
    			if (hour == 0) {
    				hour = 12;
    				meridian = 'AM';
    			}
    			
    			var minute = toDt.getMinutes();
    			
    			$(this.config.toHour).val(hour);
    			$(this.config.toMinute).val(minute);
    			$(this.config.toMeridian).val(meridian);
            }
	    	
	    	$(this.config.noToDate).trigger('setupCheckedStatus');
	    	$(this.config.noFromDate).trigger('setupCheckedStatus');
	    }
	};
	
	
	/**
	 * Sets up the all the interaction for the transition plugin
	 * 
	 * All interaction with the plugin will operate on the data that is passed to it
	 */
	var transitionPlugin = {
	
		name : 'Transition',
		config : {},
	    $sampleSlideshow : null,
	        
	    init : function(settings) {
	
	        this.config = {
	            baseUrl          : $('#baseUrl').val(),
	            transitionSelect : 'select#transition'
	        };
	        
	        $.extend(this.config, settings);
	        
	        this.$sampleSlideshow = $('<div id="sampleSlideshow"></div>');
	        
	        thisPlugin = this; 
	        $(this.config.transitionSelect).change(function() {
	            thisPlugin.startSampleSlideshow($(this).val());
	        });
	        
	        this.startSampleSlideshow();
	        
	        pluginRegistry.registerSlidePlugin(this.name, this);
	    },
	    
	    getName : function() {
	    	return this.name;
	    },
	    
	    startSampleSlideshow : function(effect) {
	       
	        this.$sampleSlideshow.empty();
	        
	        for (var i=1; i <= 2; i++) {
	            var tmp = $('<div></div>').addClass('image' + i);
	            
	            this.$sampleSlideshow.append(tmp);
	        }
	        
	        $(this.config.transitionSelect).closest('div.plugin').append(this.$sampleSlideshow);
	        
	        effect = effect || 'none';
	        
	        $(this.$sampleSlideshow).cycle({
	        	fx: effect,
	            timeout: 2000
	        });
	    },
	    
	    loadData : function(pluginData) {
	        
	        if (pluginData === undefined || pluginData.length == 0) {
	            transition = '';
	        } else {
	            transition = pluginData.transition;
	        }
	        
	    	$(this.config.transitionSelect).val(transition);
            this.startSampleSlideshow(transition);
	    },

	    /**
	     * Updates the values for the plugin with reference to the passed slide
	     * object
	     * 
	     * @param $slide Reference to the slide to act upon
	     * @return
	     */
	    update : function($slide) {
	        
	        var pluginData = {
	            transition : $(this.config.transitionSelect).val() || ''
	        };
	        
	        $slide.setPluginData(this.name, pluginData);
	    }
	};
	
})(jQuery);